﻿using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using Moonlite.Services.CodeCompletion;
using Moonlite.ExtensionApi.ControlInterfaces;
using Moonlite.Platform.General;
using Storm.TextEditor.Editor.Text;
namespace Moonlite.UI.Shell.Controls
{
    public partial class NavigateTo : Form
    {
        private AndromedaStructure structure;
        public AndromedaStructure Structure
        {
            get { return structure; }
            set { structure = value; }
        }
        private int GetObjectImageIndex(AndromedaObject @object)
        {
            if (@object is IAndromedaObjectWithImageIndex)
            {
                IAndromedaObjectWithImageIndex objectWithImageIndex = (IAndromedaObjectWithImageIndex)@object;
                return objectWithImageIndex.ImageIndex;
            }
            return -1;
        }
        private string GetObjectHierachy(AndromedaObject @object, bool includeObject)
        {
            if (@object is IAndromedaObjectWithName)
            {
                string hierachy = "";
                AndromedaObject current = includeObject ? @object : @object.Parent != null && @object.Parent is IAndromedaObjectWithName && !(@object.Parent is AndromedaSource || @object.Parent is AndromedaStructure) ? @object.Parent : @object;
                while (true)
                {
                    IAndromedaObjectWithName objectWithName = (IAndromedaObjectWithName)current;
                    hierachy = (current.Parent == null || !(current.Parent is IAndromedaObjectWithName) || current is AndromedaSource || current is AndromedaStructure ? "" : " of ") + (current is AndromedaObjectClass || current is AndromedaObjectEnrichment || current is AndromedaObjectStruct ? "type " : "") + objectWithName.Name + hierachy;
                    current = current.Parent;
                    if (current == null || !(current is IAndromedaObjectWithName) || current is AndromedaSource || current is AndromedaStructure)
                    {
                        break;
                    }
                }
                return hierachy.StartsWith(" ") ? hierachy.Substring(1) : hierachy;
            }
            return "";
        }
        private string GetObjectContext(AndromedaObject @object)
        {
            if (@object.Parent is AndromedaSource)
            {
                return "of " + new Uri(((AndromedaSource)@object.Parent).Path).LocalPath;
            }
            else
            {
                return GetObjectHierachy(@object, false);
            }
        }
        private void Search(string searchString)
        {
            if (structure == null) return;
            if (structure.Children.Count == 0)
            {
                labelResult.Text = "You have no code in your project or the parser is still parsing.";
                return;
            }
            listBoxExResults.Items.Clear();
            labelResult.Text = "Found 0 matching results.";
            if (string.IsNullOrEmpty(searchString)) return;
            string loweredSearchString = searchString.ToLower();
            progressBar.Visible = true;
            progressBar.Value = 0;
            AndromedaObjectCollection objects = structure.GetAllChildren();
            progressBar.Maximum = objects.Count;
            foreach (AndromedaObject @object in objects)
            {
                if (@object is IAndromedaObjectWithName)
                {
                    IAndromedaObjectWithName objectWithName = (IAndromedaObjectWithName)@object;
                    if (objectWithName.Name.ToLower().Contains(loweredSearchString))
                    {
                        string context = GetObjectContext(@object);
                        listBoxExResults.Items.Add(new ListBoxItemEx(objectWithName.Name + (context.Length > 0 ? " [" + context + "]" : ""), GetObjectImageIndex(@object), @object));
                        progressBar.Value++;
                        labelResult.Text = "Found " + progressBar.Value.ToString() + " matching results.";
                    }
                }
            }
            if (listBoxExResults.Items.Count > 0) listBoxExResults.SelectedIndex = 0;
            progressBar.Value = progressBar.Maximum;
            progressBar.Visible = false;
        }
        private void OnResultsSelectedIndexChanged(object sender, EventArgs e)
        {
            if (listBoxExResults.Items.Count > 0)
            {
                btnOK.Enabled = true;
            }
            else
            {
                btnOK.Enabled = false;
            }
        }
        private void OnSearchTextChanged(object sender, EventArgs e)
        {
            Search(textBoxSearch.Text);
        }
        private AndromedaSource GetObjectSource(AndromedaObject @object)
        {
            if (@object is AndromedaSource) return @object as AndromedaSource;
            AndromedaObject current = @object.Parent;
            while (current != null)
            {
                if (current is AndromedaSource) return current as AndromedaSource;
                current = current.Parent;
            }
            return null;
        }
        private void NavigateAndClose()
        {
            if (Global.Instance == null || Global.Instance.Project == null) return;
            if (listBoxExResults.SelectedIndex > -1)
            {
                AndromedaObject @object = (AndromedaObject)((ListBoxItemEx)listBoxExResults.SelectedItem).Tag;
                if (@object != null)
                {
                    AndromedaSource source = GetObjectSource(@object);
                    if (source != null)
                    {
                        ITextEditor textEditor = Global.Instance.OpenFile(new Uri(source.Path).LocalPath, GalaxyObjectHelper.GetFileFromSource(source, Global.Instance.Project));
                        if (textEditor != null)
                        {
                            TextPoint point = textEditor.InnerTextEditor.Document.IntPosToPoint(@object.Offset);
                            textEditor.InnerTextEditor.Caret.Position = point;
                            textEditor.InnerTextEditor.Caret.CropPosition();
                            textEditor.InnerTextEditor.ActiveViewControl.CenterInView(textEditor.InnerTextEditor.Caret.Position.Y);
                        }
                    }
                }
                Close();
            }
        }
        private void OnResultsMouseDoubleClick(object sender, MouseEventArgs e)
        {
            NavigateAndClose();
        }
        private void OnOKClick(object sender, EventArgs e)
        {
            NavigateAndClose();
        }
        private void OnCancelClick(object sender, EventArgs e)
        {
            Close();
        }
        public NavigateTo()
        {
            InitializeComponent();
            listBoxExResults.ImageList = AndromedaImageIndexes.GlobalImageList;
        }
    }
}
